package dbsync4j.mapper.concrete.compare;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.ResourceBundle;

import dbsync4j.core.behavior.DatabaseObject;
import dbsync4j.mapper.behavior.compare.DifferenceCompare;
import dbsync4j.mapper.behavior.diff.Difference;
import dbsync4j.utils.DBSync4JUtils;

public class ConcreteTableDifferenceCompare extends AbstractDifferenceCompare implements DifferenceCompare, Comparable<DifferenceCompare> {

	private Collection<DifferenceCompare> columnDiff;
	private Collection<DifferenceCompare> primaryKeyDiff;
	private Collection<DifferenceCompare> foreignKeyDiff;

	public ConcreteTableDifferenceCompare(DatabaseObject source, DatabaseObject destiny) {
		super(source, destiny);

		columnDiff = new ArrayList<DifferenceCompare>();
		primaryKeyDiff = new ArrayList<DifferenceCompare>();
		foreignKeyDiff = new ArrayList<DifferenceCompare>();
	}

	/* (non-Javadoc)
	 * @see dbsync4j.mapper.behavior.compare.DifferenceCompare#diff()
	 */
	@SuppressWarnings("unchecked")
	@Override
	public Collection<Difference> diff() {
		
		Collection <Difference> tableDifference = new ArrayList<Difference>();
		
		for(DifferenceCompare d :  primaryKeyDiff) {
			tableDifference.addAll(d.diff());
		}
		
		for(DifferenceCompare d :  foreignKeyDiff) {
			tableDifference.addAll(d.diff());
		}	
	
		for(DifferenceCompare d :  columnDiff) {
			tableDifference.addAll(d.diff());
		}
		
		this.differences = tableDifference;
		
		return this.differences;
	}

	/* (non-Javadoc)
	 * @see dbsync4j.mapper.behavior.compare.DifferenceCompare#addComparator(dbsync4j.mapper.behavior.compare.DifferenceCompare)
	 */
	@Override
	public void addComparator(DifferenceCompare diffCompare) {

		if(diffCompare.getClass().equals(ConcretePrimaryKeyDifferenceCompare.class)) {
			primaryKeyDiff.add(diffCompare);
		} else if(diffCompare.getClass().equals(ConcreteForeingKeyDifferenceCompare.class)) {
			foreignKeyDiff.add(diffCompare);	
		} else if(diffCompare.getClass().equals(ConcreteColumnDifferenceCompare.class)) {
			columnDiff.add(diffCompare);
		}
	}

	/* (non-Javadoc)
	 * @see dbsync4j.mapper.behavior.compare.DifferenceCompare#comparators()
	 */
	@SuppressWarnings("unchecked")
	@Override
	public Collection <DifferenceCompare> comparators() {

		Collection <DifferenceCompare> comparators = new ArrayList<DifferenceCompare>(); 
		
		comparators.addAll(primaryKeyDiff);
		comparators.addAll(foreignKeyDiff);
		comparators.addAll(columnDiff);
		
		List orderedValues = new ArrayList<DifferenceCompare>(comparators);
		Collections.sort(orderedValues);

		return comparators;
	}
	
	/* (non-Javadoc)
	 * @see java.lang.Object#toString()
	 */
	@Override
	public String toString() {

		ResourceBundle rb = DBSync4JUtils.RESOURCEBUNDLE;
		StringBuffer buffer = new StringBuffer("");

		Collection<Difference> differences = this.diff();

		DatabaseObject source = this.source;
		DatabaseObject destiny = this.destiny;

		String sName = source  == null ? rb.getString("null") : source.getName();
		String dName = destiny == null ? rb.getString("null") : destiny.getName();

		buffer.append(rb.getString("tables") + " [" + sName + ", " + dName + "]");

		if(differences.size() == 0){

			if(source == null || destiny == null) {
				buffer.append("\n" + rb.getString("nopair") + "\n");
			} else {
				buffer.append("\n" + rb.getString("noDiff") + "\n");
			}
			
		} else {
			for(Difference difference : differences) {
				buffer.append("\n" + difference + "\n");
			}
		}
		
		return buffer.toString();
	}

	@Override
	public int compareTo(DifferenceCompare td) {
		
		String tableName = td.getSource() == null ? (td.getDestiny().getName()) : td.getSource().getName();
		String tableName_ = source == null ? (destiny.getName()) : source.getName(); 
		//tableName.charAt(0) < tableName_.charAt(0) ? 1 : -1;
		return tableName_.compareTo(tableName);
	}

	public Collection<DifferenceCompare> getPrimaryKeyDifferenceCompare() {
		
		return primaryKeyDiff;
	}

	public Collection<DifferenceCompare> getForeignKeyDifferenceCompare() {
		
		return foreignKeyDiff;
	}
	
	public Collection<DifferenceCompare> getColumnDifferenceCompare() {
		
		return columnDiff;
	}
	
}
